package com.guaoran.java8concurrency.java7;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.atomic.LongAdder;

/**
 * @author : guaoran
 * @Description : <br/>
 *  Fork/Join实例，并行框架
 * @date :2018/11/24 13:26
 */
public class ForkJoinDemo2 {
    public static void main(String[] args) {
        //并行：多核参与
        //并发：一同参与
        //ForkJoin 线程池
        System.out.println("当前公用ForkJoin线程池 并行数："+
                ForkJoinPool.commonPool().getParallelism());
        System.out.println("当前CPU处理器数："+
                Runtime.getRuntime().availableProcessors());
        //类似ThreadPoolExecutor
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //一个集合进行累加
        List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        //since 1.8 累加数
        LongAdder longAdder = new LongAdder();
        //普通递归操作
        AddTask addTask = new AddTask(nums,longAdder);
        forkJoinPool.invoke(addTask);
        forkJoinPool.shutdown();
        System.out.println(longAdder);
    }
    private static class AddTask extends RecursiveAction{
        final List<Integer> nums;
        final LongAdder longAdder;
        public AddTask(List<Integer> nums, LongAdder longAdder) {
            this.nums = nums;
            this.longAdder = longAdder;
        }


        @Override
        protected void compute() {
            int size = nums.size();
            if(size>1){
                //二分部分数
                int parts = size / 2;

                //上半部分
                List<Integer> leftParts = nums.subList(0,parts);
                AddTask leftTask = new AddTask(leftParts,longAdder);
                //下半部分
                List<Integer> rightParts = nums.subList(parts,size);
                AddTask rightTask = new AddTask(rightParts,longAdder);
                //fork/join
                invokeAll(leftTask,rightTask);

            }else{
                if(size == 0){
                    return;
                }
                longAdder.add(nums.get(0));
            }
        }
    }
}

